#include <stdint.h>
#include "uart.h"
#include "clock.h"


static void __mem_data_init(void)
{
    extern uint32_t flash_data_start;
    extern uint32_t ram_data_end;
    extern uint32_t ram_data_start;

    uint8_t *pflashStart = (uint8_t *)&flash_data_start;
    uint8_t *pramStart = (uint8_t *)&ram_data_start;
    uint8_t *pramEnd = (uint8_t *)&ram_data_end; 

    for (; pramStart < pramEnd; pramStart++) {
        *pramStart++ = *pflashStart++;
    }
}

static void __mem_bss_init(void)
{
    extern uint32_t ram_bss_data_start;
    extern uint32_t ram_bss_data_end;

    uint8_t *pstart = (uint8_t *)&ram_bss_data_start;
    uint8_t *pend = (uint8_t *)&ram_bss_data_end; 

    for (; pstart < pend; pstart++) {
        *pstart++ = 0;
    }
}

void system_boot_init(void)
{
    extern int start_entry(void);

    system_clock_init();

    //mem init
    __mem_data_init();
    __mem_bss_init();

    //外设初始化
    systick_init();
    uart_init();

    start_entry();
}

/* 简单的软件除法实现 */
int __aeabi_idiv(int numerator, int denominator)
{
    int quotient = 0;
    int sign = 1;
    
    if (numerator < 0) {
        numerator = -numerator;
        sign = -sign;
    }
    
    if (denominator < 0) {
        denominator = -denominator;
        sign = -sign;
    }
    
    while (numerator >= denominator) {
        numerator -= denominator;
        quotient++;
    }
    
    return sign * quotient;
}

/* 无符号除法 */
unsigned int __aeabi_uidiv(unsigned int numerator, unsigned int denominator)
{
    unsigned int quotient = 0;
    
    while (numerator >= denominator) {
        numerator -= denominator;
        quotient++;
    }
    
    return quotient;
}

/* 取模运算 */
int __aeabi_idivmod(int numerator, int denominator)
{
    int quotient = __aeabi_idiv(numerator, denominator);
    int remainder = numerator - quotient * denominator;
    return remainder;
}

unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator)
{
    unsigned int quotient = __aeabi_uidiv(numerator, denominator);
    unsigned int remainder = numerator - quotient * denominator;
    return remainder;
}